/***********************************************************************************
 * 文件名： mcu_adc.h
 * 作者： 刘言
 * 版本： 1
 * 说明：
 * 		ADC驱动。
 *      注意：
 *          CH0和CH1比较奇怪，启用它们会导致MCU运行异常缓慢，不建议使用！
 *          通道使能过多会奇怪的降低转换速率，具体请查看示例。
 * 修改记录：
 * 	2022/12/16: 初版。 刘言。
***********************************************************************************/

#ifndef _MCU_ADC_H_
#define _MCU_ADC_H_

#include "..\ARM\typedef.h"


// 参数计算


// 自定义类型

typedef enum _adc_ch
{
    ADC_CH0 = 0, ADC_CH_PGA = 0, ADC_CH0_PGA = 0,
    ADC_CH1 = 1, ADC_CH_TEMP = 1, ADC_CH1_TEMP = 1,
    ADC_CH2 = 2, ADC_CH_P23_AIO1 = 2, ADC_DIFF_CHAP = 2, ADC_DIFF_CHA = 2,
    ADC_CH3 = 3, ADC_CH_P11_AIO0 = 3, ADC_DIFF_CHAN = 3,
    ADC_CH4 = 4, ADC_CH_P14_AIO3 = 4, ADC_DIFF_CHBP = 4, ADC_DIFF_CHB = 4,
    ADC_CH5 = 5, ADC_CH_P24_AIO2 = 5, ADC_DIFF_CHBN = 5,
    ADC_CH6 = 6, ADC_CH_P20_AIO9 = 6, ADC_DIFF_CHCP = 6, ADC_DIFF_CHC = 6,
    ADC_CH7 = 7, ADC_CH_P15_AIO4 = 7, ADC_DIFF_CHCN = 7,
    ADC_CH_VOICE = 8
}adc_ch_t;

typedef enum _adc_ch_mask
{
    ADC_CH0_MASK = (1 << ADC_CH0),
    ADC_CH1_MASK = (1 << ADC_CH1),
    ADC_CH2_MASK = (1 << ADC_CH2),
    ADC_CH3_MASK = (1 << ADC_CH3),
    ADC_CH4_MASK = (1 << ADC_CH4),
    ADC_CH5_MASK = (1 << ADC_CH5),
    ADC_CH6_MASK = (1 << ADC_CH6),
    ADC_CH7_MASK = (1 << ADC_CH7),
    ADC_CH_ALL_MASK = 0XFF
}adc_ch_mask_t;

/**
 * 回调函数的类型
 * @param   ch  通道
 * @param   result  结果
*/
typedef void (*adc_cb_t)(adc_ch_t ch, u16 result);


////////////////////// APIs

//////////// 基础API

/**
 * ADC初始化，注意没有开启时钟门控，未配置管脚，ADC默认使能
 * ADC中断入口函数已经被ADC驱动实现，使用者不要再重复定义。
*/
void Adc_Init();

/**
 * 批量使能ADC通道，不影响已经使能的通道（可以多次添加通道）。
 * \目前ADC仅支持自动扫描模式且默认开启，使能的通道将会加入扫描。
 * @param   ch_mask  通道掩码，用 | 连接多个通道。
*/
void Adc_Enable(adc_ch_mask_t ch_mask);

/**
 * 批量关闭（失能）ADC通道以省电。注意：关闭状态下开始转换可能会把程序锁死。所有通道关闭
 * 后ADC模块关闭。
 * @param   ch_mask  通道掩码，用 | 连接多个通道。
*/
void Adc_Disable(adc_ch_mask_t ch_mask);

/**
 * 获取转换结果。注意：需要先把对应通道的IO口设置为模拟信号模式。
 * 获取的是最后一次转换结果还是立即触发转换并等待结果取决于配置 _ADC_DIRECT_RESULT 。
 * @param   ch  通道号
 * @return  AD转换值
*/
u16 Adc_GetResult(adc_ch_t ch);

/**
 * 获取ADC满值（最大值）
 * @return ADC满量程值(实际上是4095，这里设置为4096加快计算)
*/
#define Adc_GetFullValue() (4096)

/**
 * 获取当前参考电压(mV)
 * @return 当前参考电压(mV)
*/
#define Adc_GetVrefVoltage() (800)


//////////// 高级 API

/**
 * 获取一次中值滤波AD值。注意：需要先把对应通道的IO口设置为模拟信号模式。
 * 获取的是最后一次转换结果还是立即触发转换并等待结果取决于配置 _ADC_DIRECT_RESULT 。
 * @param   ch  通道号
 * @param   dat_num  中值滤波采样数据数量，最大64.
 * @return  AD转换值
*/
u16 Adc_GetFiltResult(adc_ch_t ch, u8 dat_num);

/**
 * 设置回调函数，当转换完毕时会有通知。注意回调函数运行在中断线程。
 * @param   ch  通道号
 * @param   cb  对应通道的回调函数
*/
void Adc_SetCb(adc_ch_t ch, adc_cb_t cb);

// /**
//  * [异步]开始（启动）一次（扫描）转换，完成后结束并回掉通知。如果正在自动扫描将会插入
//  * 本次转换。
//  * 可在配置文件中分别设置每个通道转换完成的条件（单次，还是多次滤波）。
//  * \目前ADC仅支持自动扫描模式且默认开启，调用本函数实际上是标记接下来转换完成后调用一
//  * 次这些通道的回掉函数。
//  * @param   ch_mask  通道掩码，用 | 连接多个通道。
// */
// void Adc_Start(adc_ch_mask_t ch_mask);

/**
 * [异步]开始自动扫描通道，将会自动扫描这些通道，可以随时读取通道转换值，每次通道转换完毕
 * 后有回掉通知。需要同时使能通道才有效。
 * 可在配置文件中分别设置每个通道调用回掉函数的触发条件（转换完成的条件,每次更新，还是
 * 滤波后的值有更新）。
 * \目前ADC仅支持自动扫描模式且默认开启，调用本函数实际上是标记接下来每次转换完成都调
 * 用这些通道的回调函数。
 * @param   ch_mask  通道掩码，用 | 连接多个通道。
*/
void Adc_StartAutoScan(adc_ch_mask_t ch_mask);

/**
 * 停止自动扫描通道。
 * \目前ADC仅支持自动扫描模式且默认开启，调用本函数实际上是清除需要调用回掉函数的标记。
 * @param   ch_mask  通道掩码，用 | 连接多个通道。
*/
void Adc_StopAutoScan(adc_ch_mask_t ch_mask);

/**
 * 查忙，当自动扫描时将始终忙。
 * \目前ADC仅支持自动扫描模式且默认开启，调用本函数实际上是返回是否在等待转换完毕（阻塞，便于多线程判断）。
 * @return true:正在转换，false:空闲。
*/
bool Adc_IsBusy();

/**
 * 获取一次中值滤波电压值。注意：需要先把对应通道的IO口设置为模拟信号模式。
 * 获取的是最后一次转换结果还是立即触发转换并等待结果取决于配置 _ADC_DIRECT_RESULT 。
 * 注意，如果启用了衰减，获取的已经是管脚上的电压。
 * @param   ch  通道号
 * @param   dat_num  中值滤波采样数据数量，最大64.
 * @return  电压值 mV
*/
u16 Adc_GetVoltage(adc_ch_t ch, u8 dat_num);

/**
 * 使用AD值计算电压值。
 * 注意，如果启用了衰减建议使用本函数计算电压，获取的已经是管脚上的电压。
 * @param   ch  通道号
 * @param   adv  AD值.
 * @return  电压值 mV
*/
u16 Adc_CalVoltage(adc_ch_t ch, u16 adv);


// void Adc_SetVref(adc_vref_t vref);

#endif


